#include "STC89C5xRC.H"
#include "sys.h"
#include "tim.h"
#include "task.h"
#include "segment.h"
#include "i_key.h"
#include "ir1838.h"
#include "m_led.h"
#include "step_motor.h"

/* define tim_0 panel start */
// static volatile tim_t tim_0_panel;   /* !> count time */
static volatile tim_THL s_tim_0_THL; /* !> tim_0 TH TL */
static volatile tim_THL s_tim_1_THL; /* !> tim_1 TH TL */
/* define tim_0 panel end */

/* define user static data start */
static volatile uint8_t s_task_num_tick;
/* define user static data end */

/**
 * @brief Timer0 interrupt routine
 *
 */
void tm0_isr() interrupt 1
{
    TL0 = s_tim_0_THL.TL; // initial timer0 low byte
    TH0 = s_tim_0_THL.TH; // initial timer0 high byte

    /* tick count start */
    for (s_task_num_tick = 0; s_task_num_tick < task_num(); s_task_num_tick++)
    {
        task_handle()[s_task_num_tick].tick--;
    }
    /* tick count end */
}

/**
 * @brief Timer1 interrupt routine
 *
 */
void tm1_isr() interrupt 3
{
#if !IR1838_TASK
    TL1 = s_tim_1_THL.TL; // initial timer1 low byte
    TH1 = s_tim_1_THL.TH; // initial timer1 high byte

#if SEGMENT_INTERRUPT_TASK
    /* segment dis interrupt start */
    segment_refresh_interrupt();
    /* segment dis interrupt end */
#endif
#if M_LED_TASK
    /* matrix_led dis interrupt start */
    matrix_led_demo();
    /* matrix_led dis interrupt end */
#endif
#if STEP_MOTOR_TASK
    step_motor_interrupt();
#endif

#else
    ir1838_struct_panel()->ir_time++; // 用于计数2个下降沿之间的时间
#endif
}

/**
 * @brief tm0_init
 *
 * @param time (0-65)ms
 *
 * @note time = (12/FOSC us) * count_num us
 * @note THL0 = 65536 - count_num
 * @note TH0 = THL0>>8
 * @note TL0 = THL0
 */
void tm0_init(uint16_t time)
{
    /* calculate THL start */
    s_tim_0_THL.TL = (65536 - (FOSC / SYS_CLK_MODE / (1000 / time)));
    s_tim_0_THL.TH = (65536 - (FOSC / SYS_CLK_MODE / (1000 / time))) >> 8;
    /* calculate THL end */
    TMOD = 0x01 | TMOD;   // set timer0 as mode1 (16-bit)
    TL0 = s_tim_0_THL.TL; // initial timer0 low byte
    TH0 = s_tim_0_THL.TH; // initial timer0 high byte
    TR0 = 1;              // timer0 start running
    ET0 = 1;              // enable timer0 interrupt
    EA = 1;               // open global interrupt switch
}

/**
 * @brief tm1_init
 *
 * @param time (0-65)ms
 *
 * @note time = (12/FOSC us) * count_num us
 * @note THL1 = 65536 - count_num
 * @note TH1 = THL1>>8
 * @note TL1 = THL1
 */
void tm1_init(uint16_t time)
{
#if !IR1838_TASK
    /* calculate THL start */
    s_tim_1_THL.TL = (65536 - (FOSC / SYS_CLK_MODE / (1000 / time)));
    s_tim_1_THL.TH = (65536 - (FOSC / SYS_CLK_MODE / (1000 / time))) >> 8;
    /* calculate THL end */
    TMOD = 0x10 | TMOD;   // set timer1 as mode1 (16-bit)
    TL1 = s_tim_0_THL.TL; // initial timer1 low byte
    TH1 = s_tim_0_THL.TH; // initial timer1 high byte
    TR1 = 1;              // timer1 start running
    ET1 = 1;              // enable timer1 interrupt
    EA = 1;               // open global interrupt switch
#else
    TMOD = TMOD | 0x20; // set timer1 as mode2 (8-bit)
    TH1 = 0x00;         // initial timer1 high byte -> 256*12/11.059200=278us=0.278ms
    TL1 = 0x00;         // initial timer1 low byte -> 256*12/11.059200=278us=0.278ms
    ET1 = 1;            // enable timer1 interrupt
    TR1 = 1;            // timer1 start running
    EA = 1;             // open global interrupt switch
#endif
}
